Imports System.ComponentModel
Imports Aricie.DNN.UI.Attributes
Imports Aricie.Collections
Imports Aricie.DNN.Caching
Imports Aricie.ComponentModel
Imports DotNetNuke.UI.WebControls
Imports System.IO
Imports Aricie.DNN.Caching.Analysis.Graphs
Imports Aricie.DNN.UI.WebControls.EditControls
Imports QuickGraph.Serialization
Imports System.Xml.Serialization
Imports System.Xml

Namespace Aricie.DNN.Caching.Analysis
    <Serializable()> _
    Public Class CacheAnalysis

        Private _ComputationDate As Date = Now

        Private _GeneratedBy As String = ""

        <NonSerialized()> _
        Private _AnalysisGraph As New DistributedCachingGraph

        Private _GroupStrategies As New List(Of CacheGroupInfo)

        Private _Statistics As New CacheStatistics

        <ExtendedCategory("MetaData")> _
            <MainCategory()> _
            <IsReadOnly(True)> _
        Public Property ComputationDate() As Date
            Get
                Return _ComputationDate
            End Get
            Set(ByVal value As Date)
                _ComputationDate = value
            End Set
        End Property

        <ExtendedCategory("MetaData")> _
            <IsReadOnly(True)> _
        Public Property GeneratedBy() As String
            Get
                Return _GeneratedBy
            End Get
            Set(ByVal value As String)
                _GeneratedBy = value
            End Set
        End Property

        <XmlIgnore()> _
            <ExtendedCategory("AnalysisGraph")> _
            <IsReadOnly(True)> _
            <Editor(GetType(GraphEditControl), GetType(EditControl))> _
            <LabelMode(LabelMode.Top)> _
        Public Property AnalysisGraph() As DistributedCachingGraph
            Get
                If _AnalysisGraph Is Nothing Then
                    _AnalysisGraph = New DistributedCachingGraph(False)
                    'For Each keyStat As KeyValuePair(Of String, CacheKeyStatistics) In Me._StatsByKey
                    '    For Each nextK As KeyValuePair(Of String, Integer) In keyStat.Value.NextKeys
                    '        If nextK.Value > 1 AndAlso _StatsByKey.ContainsKey(nextK.Key) Then
                    '            Dim tag As New CacheSequenceTag(nextK.Value, _
                    '                        Convert.ToInt32((100 * nextK.Value / keyStat.Value.Diagnostic.UsualNextKey.TotalCount)), _
                    '                        keyStat.Value.Diagnostic.UsualNextKey.Key = nextK.Key)
                    '            _StatisticsGraph.AddVerticesAndEdge(New CacheKeyStatisticsEdge(Me.GetNode(keyStat.Key), Me.GetNode(nextK.Key), tag))
                    '        End If
                    '    Next
                    'Next
                End If
                Return _AnalysisGraph
            End Get
            Set(ByVal value As DistributedCachingGraph)
                Me._AnalysisGraph = value
            End Set
        End Property


        Private _XMLNodes As SerializableDictionary(Of String, DistributedCachingNode)

        <Browsable(False)> _
        Public Property XMLNodes() As SerializableDictionary(Of String, DistributedCachingNode)
            Get
                If _XMLNodes Is Nothing Then
                    _XMLNodes = New SerializableDictionary(Of String, DistributedCachingNode)
                    For Each v As DistributedCachingNode In Me.AnalysisGraph.Vertices
                        _XMLNodes.Add(v.ToString, v)
                    Next
                End If
                Return _XMLNodes
            End Get
            Set(ByVal value As SerializableDictionary(Of String, DistributedCachingNode))
                Me._XMLNodes = value
            End Set
        End Property

        Private _XMLEdges As SerializableDictionary(Of String, DistributedCachingEdge)

        <Browsable(False)> _
        Public Property XMLEdges() As SerializableDictionary(Of String, DistributedCachingEdge)
            Get
                If _XMLEdges Is Nothing Then
                    _XMLEdges = New SerializableDictionary(Of String, DistributedCachingEdge)
                    For Each e As DistributedCachingEdge In Me.AnalysisGraph.Edges
                        _XMLEdges.Add(e.ToString, e)
                    Next
                End If
                Return _XMLEdges
            End Get
            Set(ByVal value As SerializableDictionary(Of String, DistributedCachingEdge))
                _XMLEdges = value
            End Set
        End Property

        <Browsable(False)> _
        Public Property GmlAnalysisGraph() As String
            Get
                Using writer As New StringWriter
                    Dim settings As New XmlWriterSettings
                    settings.Indent = True
                    Using xWriter As XmlWriter = XmlWriter.Create(writer, settings)
                        GraphMLExtensions.SerializeToGraphML(Of DistributedCachingNode, DistributedCachingEdge, DistributedCachingGraph)(Me.AnalysisGraph, _
                                                                                                                                         xWriter, AddressOf DistributedCachingNode.Identity, AddressOf DistributedCachingEdge.Identity)
                    End Using
                    Return writer.ToString
                End Using
            End Get
            Set(ByVal value As String)
                Using reader As New StringReader(value)
                    Using xReader As New XmlTextReader(reader)
                        Me._AnalysisGraph = New DistributedCachingGraph(False)
                        Dim serializer As New GraphMLDeserializer(Of DistributedCachingNode, DistributedCachingEdge, DistributedCachingGraph)()
                        serializer.Deserialize(xReader, Me._AnalysisGraph, AddressOf Me.IdentifiableVertexFactory, AddressOf Me.IdentifiableEdgeFactory)

                    End Using
                End Using


            End Set
        End Property

        Public Function IdentifiableVertexFactory(ByVal id As String) As DistributedCachingNode
            Try
                Return Me._XMLNodes(id)
            Catch ex As Exception
                Dim strKeys As New StringBuilder
                For Each key As String In Me._XMLNodes.Keys
                    strKeys.Append(key)
                Next
                Dim newEx As New ArgumentException(String.Format("Vertex Missmatch, id: {0} , ids: {1}", id, strKeys.ToString), "id", ex)
                Throw newEx
            End Try

        End Function

        Public Function IdentifiableEdgeFactory(ByVal source As DistributedCachingNode, ByVal target As DistributedCachingNode, ByVal id As String) As DistributedCachingEdge
            Try
                Return New DistributedCachingEdge(source, target, Me.XMLEdges(id).Tag)
            Catch ex As Exception
                Dim strKeys As New StringBuilder
                For Each key As String In Me._XMLEdges.Keys
                    strKeys.Append(key)
                Next
                Dim newEx As New ArgumentException(String.Format("Edge Missmatch, id: {0} , ids: {1}", id, strKeys.ToString), "id", ex)
                Throw newEx
            End Try
        End Function



        'Public Property XmlAnalysisGraph() As String 'XmlSerializableGraph(Of DistributedCachingNode, DistributedCachingEdge, DistributedCachingGraph)
        '    Get
        '        Dim sb As New StringBuilder
        '        Using tw As New StringWriter(sb)
        '            Using xw As New System.Xml.XmlTextWriter(tw)
        '                xw.Formatting = System.Xml.Formatting.Indented
        '                SerializationExtensions.SerializeToXml(Of DistributedCachingNode, DistributedCachingEdge, DistributedCachingGraph)(Me.AnalysisGraph, xw, _
        '                                    AddressOf DistributedCachingNode.Identity, AddressOf DistributedCachingEdge.Identity, "Group", "Key", "Sequence", "http://www.aricie.com")
        '                Return sb.ToString
        '            End Using
        '        End Using
        '        'Return New XmlSerializableGraph(Of DistributedCachingNode, DistributedCachingEdge, DistributedCachingGraph)(Me.AnalysisGraph)
        '    End Get
        '    Set(ByVal value As String)
        '        Using sr As New StringReader(value)
        '            Using xr As New XmlTextReader(sr)
        '                Me._AnalysisGraph = SerializationExtensions.DeserializeFromXml(Of DistributedCachingNode, DistributedCachingEdge, DistributedCachingGraph)(xr, _
        '                                        AddressOf DistributedCachingGraph.AllGraphsPredicate, _
        '                                        AddressOf DistributedCachingNode.AllNodes, _
        '                                        AddressOf DistributedCachingEdge.AllEdgesPredicate, _
        '                                    AddressOf DistributedCachingGraph.Factory, _
        '                                    AddressOf DistributedCachingNode.Factory, _
        '                                    AddressOf DistributedCachingEdge.Factory)
        '            End Using
        '        End Using


        '        'Me._AnalysisGraph = value.Graph
        '    End Set
        'End Property

        <ExtendedCategory("GroupStrategies")> _
            <Editor(GetType(ListEditControl), GetType(EditControl))> _
            <CollectionEditor(False, False, True, True, 10)> _
            <LabelMode(LabelMode.Top)> _
        Public Property GroupStrategies() As List(Of CacheGroupInfo)
            Get
                Return _GroupStrategies
            End Get
            Set(ByVal value As List(Of CacheGroupInfo))
                _GroupStrategies = value
            End Set
        End Property



        <ExtendedCategory("BaseStatistics")> _
            <Editor(GetType(PropertyEditorEditControl), GetType(EditControl))> _
            <LabelMode(LabelMode.Top)> _
        Public Property Statistics() As CacheStatistics
            Get
                Return _Statistics
            End Get
            Set(ByVal value As CacheStatistics)
                _Statistics = value
            End Set
        End Property


    End Class
End Namespace